import Constant from "@/config/constant";
import {AnyParams, HttpResponse, SetLoadingType} from "@/common/httptypes";
import LoginUser from "@/config/user";
import qs from "qs";
import {util} from "@/common/util";
import {notification} from "antd";

export type HttpParamsProps = {
    body?: AnyParams<any>
    params?: AnyParams<any>
}
export type HttpMethodProps<D> = {
    setLoading?: SetLoadingType
    success?: (data: D) => void
    successOnZero?: (data: HttpResponse<D>) => void
    failure?: () => void
}
export type  ReqProps<D> = HttpMethodProps<D> & HttpParamsProps;


class HttpClient {
    BaseUrl: string;

    constructor(baseUrl: string) {
        this.BaseUrl = baseUrl;
    }

    doPost<D>(url: string, props: ReqProps<D>) {
        const config: RequestInit = {}
        config.headers = new Headers();
        config.headers.set("Content-Type", "application/json;charset=utf-8")
        config.method = "POST"
        config.body = JSON.stringify(props.body)
        DoHooksRequest(this.BaseUrl, url, props, config)
    }

    doPostForm<D>(url: string, props: ReqProps<D>) {
        const config: RequestInit = {}
        config.headers = new Headers();
        config.headers.set("Content-Type", "application/x-www-form-urlencoded;charset=utf-8")
        config.method = "POST"
        config.body = qs.stringify(props.body)
        DoHooksRequest(this.BaseUrl, url, props, config)
    }

    doGet<D>(url: string, props: ReqProps<D>) {
        const config: RequestInit = {}
        config.headers = new Headers();
        config.headers.set("Content-Type", "application/x-www-form-urlencoded;charset=utf-8")
        config.method = "GET"
        DoHooksRequest(this.BaseUrl, url, props, config)
    }

    post(url: string, props: HttpParamsProps): Promise<Response> {
        const config: RequestInit = {}
        config.headers = new Headers();
        config.headers.set("Content-Type", "application/json;charset=utf-8")
        config.method = "POST"
        config.body = JSON.stringify(props.body)
        return DoRequest(this.BaseUrl, url, props, config)
    }

    postForm(url: string, props: HttpParamsProps): Promise<Response> {
        const config: RequestInit = {}
        config.headers = new Headers();
        config.headers.set("Content-Type", "application/x-www-form-urlencoded;charset=utf-8")
        config.method = "POST"
        config.body = qs.stringify(props.body)
        return DoRequest(this.BaseUrl, url, props, config)
    }

    get(url: string, props: HttpParamsProps): Promise<Response> {
        const config: RequestInit = {}
        config.headers = new Headers();
        config.headers.set("Content-Type", "application/x-www-form-urlencoded;charset=utf-8")
        config.method = "GET"
        return DoRequest(this.BaseUrl, url, props, config)
    }
}


export async function ParseResponse(response: Response) {
    if (response.ok) {
        const result = await response.json()
        if (result.code === 0) {
            return result.data
        } else if (result.code === -1) {
            notification.error({message: result.err.msg, duration: 1, onClose: () => util.toLogin()})
        } else {
            notification.error({message: result.err.msg})
        }
    } else if (response.status < 500) {
        notification.warning({message: "【" + response.status + "】 " + response.statusText})
    } else if (response.status === 503) {
        notification.warning({message: "权限不足"})
    } else if (response.status === 504) {
        notification.error({message: "服务不可用/请联系管理员"})
    } else {
        notification.error({message: "服务异常"})
    }
    return undefined
}

function DoHooksRequest<D>(baseUrl: string, url: string, props: ReqProps<D>, config: RequestInit) {
    let {setLoading, success, successOnZero, failure} = props;
    let loading = true
    setLoading?.(loading)
    DoRequest(baseUrl, url, props, config).then(response => {
        setLoading?.(false);
        if (response.status === 200) {
            response.json().then(result => {
                if (result.code === 0) {
                    success?.(result.data)
                    if (config.method === "POST") {
                        notification.success({message: "操作成功"})
                    }
                } else if (result.code === -1) {
                    notification.error({message: result.err.msg, duration: 1, onClose: () => util.toLogin()})
                } else {
                    notification.error({message: result.err.msg})
                    successOnZero?.(result)
                }
            })
        } else if (response.status < 500) {
            notification.warning({message: "【" + response.status + "】 " + response.statusText})
        } else if (response.status === 503) {
            notification.warning({message: "权限不足"})
        } else if (response.status === 504) {
            notification.error({message: "服务不可用/请联系管理员"})
        } else {
            failure?.()
            notification.error({message: "服务异常"})
        }
    }).catch(res => {
        setLoading?.(false);
        failure?.()
        notification.error({message: "网络异常"})
    })
}


function DoRequest(baseUrl: string, url: string, props: HttpParamsProps, config: RequestInit): Promise<Response> {
    url = util.joinUrl(url, qs.stringify(props.params))
    const headers = config.headers as (Headers)

    LoginUser.sync()
    if (LoginUser.token) {
        headers.set("token", LoginUser.token)
    }
    config.credentials = "include"
    return fetch(`${baseUrl}${url}`, config)
}


const Http = new HttpClient(Constant.NODE_ENV === "development" ? "" : "")
export default Http;